<?php
abstract class CmsBaseUserModel extends Model
{
    protected $sessionName;
    protected $miniumPasswordLength = 6;

    public function IsLoggedIn()
    {
        return Session::IsExisted($this->sessionName) && $this->GetCurrentUserId();
    }

    public function Logout()
    {
        Session::Remove($this->sessionName);
    }

    public function GetCurrentUserId()
    {
        return Session::Get($this->sessionName);
    }

    public function Login($user)
    {
        $id = $this->LoginWithEmailPassword($user['email'], $user['password']);
        if ($id)
            Session::Set($this->sessionName, $id);
        else
            throw new Exception('Login failed');
    }

    public function LoginWithEmailPassword($email, $password)
    {
        $cond = new SqlCondition();
        $cond->AddString('email', $email);
        $cond->AddString('password', md5($password));
        return $this->FindScalar($cond, 'id');
    }

    public function Register($user)
    {
        $this->ValidatePassword($user['password'], $user['confirm_password']);
        return $this->Insert($user);
    }

    protected function ValidateBeforeInsert(&$item)
    {
        parent::ValidateBeforeInsert($item);
        $this->CheckExistedUserName($item['username']);
        $this->ValidateEmail($item['email']);
        $this->ValidateConfirmEmail($item['email'], $item['confirm_email']);
        $this->CheckExistedEmail($item['email']);
    }
    public function CheckUrl($url)
    {
        if(!$this->IsUrl($url))
            throw new Exception("Website is not valid.");
    }

    public function IsUrl($url)
    {
        return preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url);
    }

    public function CheckExistedUserName($username)
    {
        if($this->IsExistedUserName($username))
            throw new Exception("User name is existed.");
    }

    public function CheckExistedEmail($email)
    {
        if($this->IsExistedEmail($email))
            throw new Exception("Email is existed.");
    }

    protected function IsExistedEmail($email)
    {
        $cond = new SqlCondition('email = @email');
        $cond->AddString('email', $email);
        $number_mail = $this->Count($cond);
        if($number_mail > 0)
            return true;
        else
            return false;
    }

    protected function IsExistedUserName($username)
    {
        $cond = new SqlCondition('username = @username');
        $cond->AddString('username', $username);
        $number_user = $this->Count($cond);
        if($number_user > 0)
            return true;
        else
            return false;
    }

    protected function ValidateEmail($email)
    {
        if (!$email)
            throw new Exception('Email is empty');
        if (!String::IsValidEmail($email))
            throw new Exception('Email is not valid');
    }

    protected function ValidatePassword($password, $confirmPassword)
    {
        if (empty($password))
            throw new Exception('Password is empty');
        if ($this->miniumPasswordLength && strlen($password) < $this->miniumPasswordLength)
            throw new Exception("Password must contain at least {$this->miniumPasswordLength} characters");
        if ($password != $confirmPassword)
            throw new Exception('Confirm password does not match');
    }

    protected function ValidateConfirmEmail($email, $confirmEmail)
    {
        if (empty($email))
            throw new Exception('Email is empty');
        if ($email != $confirmEmail)
            throw new Exception('Confirm email does not match');
    }

    public function GetGroupIdById($id)
    {
        return $this->FindScalarById($id, 'group_id');
    }

    public function Insert($item)
    {
        $item['password'] = $this->PasswordHash($item['password']);
        return parent::Insert($item);
    }

    protected function PasswordHash($plaintext)
    {
        return md5($plaintext);
    }

    public function Update($item)
    {
        $item = $this->GetDataChanged($item);
        if(count($item) > 1)
        {
            if(isset($item['password']))
            {
                $this->ValidatePassword($item['password'], $item['confirm_password']);
                $item['password'] = $this->PasswordHash($item['password']);
            }
            if(isset($item['email']))
            {
                $this->ValidateEmail($item['email']);
                $this->CheckExistedEmail($item['email']);
            }
            if(isset($item['website']))
            {
                $this->CheckUrl($item['website']);
            }
            return parent::Update($item);
        }
    }

    public function GetDataChanged($item)
    {
        $before_update = $this->FindOneBy('id', $item['id']);
        foreach($item as $key => $value)
        {
            if(isset($before_update[$key]) && $value == $before_update[$key] && $key != 'id')
            {
                unset($item[$key]);
            }
        }
        if(!isset($item['password']))
            unset($item['confirm_password']);
        return $item;
    }

    public function GetCurrentUser()
    {
        if ($id = $this->GetCurrentUserId())
            return $this->FindById($id);
    }

    public function GetUsernameById($id)
    {
        return $this->FindScalarById($id, 'username');
    }
}
?>
